package com.bwt.top.bwt_ad_flutter.manager;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.bwt.top.bwt_ad_flutter.BwtAdFlutterPlugin;
import com.bwt.top.bwt_ad_flutter.ad.BwtSplashAdActivity;
import com.bwt.top.bwt_ad_flutter.ad.BwtUnifiedAd;
import com.bwt.top.bwt_ad_flutter.config.BwtAdMethodConfig;
import com.bwt.top.bwt_ad_flutter.config.BwtAdParamConfig;
import com.bwt.top.bwt_ad_flutter.config.BwtAdViewTypeConfig;
import com.bwt.top.bwt_ad_flutter.listener.OnAdReleaseListener;
import com.bwt.top.bwt_ad_flutter.listener.SimpleActivityLifecycleCallbacks;
import com.bwt.top.bwt_ad_flutter.model.AdParams;
import com.bwt.top.bwt_ad_flutter.util.LogUtil;
import com.bwt.top.bwt_ad_flutter.view.factory.BwtBannerAdFactory;
import com.bwt.top.bwt_ad_flutter.view.factory.BwtNativeExpressAdFactory;
import com.bwt.top.bwt_ad_flutter.view.factory.BwtServiceAdFactory;
import com.bwt.top.bwt_ad_flutter.view.factory.BwtUnifiedAdFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.flutter.Log;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;

public class BwtAdManager {
    @SuppressLint("StaticFieldLeak")
    private static BwtAdManager instance;
    private MethodChannel channel;
    private BwtNativeExpressAdFactory bwtNativeExpressAdFactory;

    private BwtBannerAdFactory bwtBannerAdFactory;
    private BwtUnifiedAdFactory bwtUnifiedAdFactory;
    private BwtServiceAdFactory bwtServiceAdFactory;

    private Application application;
    private Context context;
    private final List<Activity> activityList = new ArrayList<>();
    private final List<OnAdReleaseListener> onAdReleaseListenerList = new ArrayList<>();
    private final SimpleActivityLifecycleCallbacks lifecycleCallbacks = new SimpleActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
            activityList.add(activity);
        }

        @Override
        public void onActivityStarted(@NonNull Activity activity) {
            if (!activityList.contains(activity)) {
                activityList.add(activity);
            }
        }

        @Override
        public void onActivityDestroyed(@NonNull Activity activity) {
            activityList.remove(activity);
        }
    };

    private BwtAdManager() {
    }

    public static BwtAdManager getInstance() {
        if (instance == null) {
            synchronized (BwtAdManager.class) {
                if (instance == null) {
                    instance = new BwtAdManager();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化
     */
    public void init(@NonNull FlutterPlugin.FlutterPluginBinding flutterPluginBinding, @NonNull BwtAdFlutterPlugin plugin) {
        try {
            unInit();
            context = flutterPluginBinding.getApplicationContext();
            application = (Application) context;
            application.registerActivityLifecycleCallbacks(lifecycleCallbacks);
            channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "bwt_ad_flutter");
            channel.setMethodCallHandler(plugin);

            bwtNativeExpressAdFactory = new BwtNativeExpressAdFactory();
            bwtBannerAdFactory = new BwtBannerAdFactory();
            bwtUnifiedAdFactory = new BwtUnifiedAdFactory();
            bwtServiceAdFactory = new BwtServiceAdFactory();
            // 注册自定义视图
            flutterPluginBinding.getPlatformViewRegistry().registerViewFactory(BwtAdViewTypeConfig.VIEW_TYPE_NATIVE_EXPRESS_AD, bwtNativeExpressAdFactory);
            flutterPluginBinding.getPlatformViewRegistry().registerViewFactory(BwtAdViewTypeConfig.VIEW_TYPE_NATIVE_BANNER_AD, bwtBannerAdFactory);
            flutterPluginBinding.getPlatformViewRegistry().registerViewFactory(BwtAdViewTypeConfig.VIEW_TYPE_UNIFIED_AD, bwtUnifiedAdFactory);
            flutterPluginBinding.getPlatformViewRegistry().registerViewFactory(BwtAdViewTypeConfig.VIEW_TYPE_SERVICE_AD, bwtServiceAdFactory);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * Flutter调用了原生方法
     */
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        Context ctx = getCurrContext();
        if (ctx == null) return;

        AdParams adParams = AdParams.parse(call);
        LogUtil.log("当前调用的原生方法为: " + call.method + ", 请求参数为: " + adParams.getString());

        switch (call.method) {
            case BwtAdMethodConfig.METHOD_INIT: {
                // 初始化广告SDK
                InitManager.init(ctx, adParams.getAppId(), adParams.getLogType(), adParams.getWechatAppId());
                result.success(true);
                break;
            }
            case BwtAdMethodConfig.METHOD_LOAD_SPLASH_AD: {
                // 加载并展示开屏广告
                if (InitManager.isBwtInited()) {
                    BwtSplashAdActivity.start(ctx, adParams);
                } else {
                    InitManager.setBwtInitCallback(b -> BwtSplashAdActivity.start(ctx, adParams));
                }
                result.success(true);
                break;
            }
            case BwtAdMethodConfig.METHOD_LOAD_INTERSTITIAL_AD:
                // 加载插屏广告
                BwtInterstitialAdManager.getInstance().loadInterstitialAd(ctx, adParams, false);
                break;
            case BwtAdMethodConfig.METHOD_SHOW_INTERSTITIAL_AD:
                // 展示插屏广告
                BwtInterstitialAdManager.getInstance().showInterstitialAd(adParams);
                break;
            case BwtAdMethodConfig.METHOD_LOAD_THEN_SHOW_INTERSTITIAL_AD:
                // 加载并展示插屏广告
                BwtInterstitialAdManager.getInstance().loadInterstitialAd(ctx, adParams, true);
                break;
            case BwtAdMethodConfig.METHOD_LOAD_NATIVE_EXPRESS_AD:
                BwtNativeExpressAdManager.getInstance().loadNativeExpressAd(ctx, adParams);
                break;
            case BwtAdMethodConfig.METHOD_RELEASE_AD: {
                // 释放广告
                loopNotifyOnAdRelease(adParams.getAdId());
                result.success(true);
                break;
            }case BwtAdMethodConfig.METHOD_LOAD_BANNER_AD: {
                BwtBannerAdManager.getInstance().loadBannerAd(ctx, adParams, true);
                break;
            }case BwtAdMethodConfig.METHOD_LOAD_NATIVE_AD: {
                BwtUnifiedAdManager.getInstance().loadUnifiedAd(ctx,adParams,true);
                break;
            }case BwtAdMethodConfig.METHOD_LOAD_SERVICE_AD: {
                BwtServiceAdManager.getInstance().loadServiceAd(ctx,adParams,true);
                break;
            }case BwtAdMethodConfig.METHOD_CLOSE_NATIVE_AD: {
                BwtUnifiedAdManager.getInstance().closeAd(adParams.getAdId());
                break;
            }
            default:
                result.notImplemented();
                break;
        }
    }

    /**
     * 注销初始化
     */
    public void unInit() {
        try {
            context = null;
            if (application != null) {
                application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks);
                application = null;
            }
            activityList.clear();
            onAdReleaseListenerList.clear();
            if (channel != null) {
                channel.setMethodCallHandler(null);
                channel = null;
            }
            if (bwtNativeExpressAdFactory != null) {
                bwtNativeExpressAdFactory.release();
            }
            if (bwtBannerAdFactory != null) {
                bwtBannerAdFactory.release();
            }
            if (bwtUnifiedAdFactory != null) {
                bwtUnifiedAdFactory.release();
            }

        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 注册广告被释放监听
     */
    public void registerOnAdReleaseListener(@NonNull OnAdReleaseListener listener) {
        onAdReleaseListenerList.add(listener);
    }

    /**
     * 注销广告释放监听
     */
    public void unregisterOnAdReleaseListener(@NonNull OnAdReleaseListener listener) {
        onAdReleaseListenerList.remove(listener);
    }

    /**
     * 发送广告消息到Flutter端
     *
     * @param event    消息类型
     * @param adParams 广告参数
     */
    public void postAdEvent(@NonNull String event, @NonNull AdParams adParams) {
        postAdEvent(event, adParams, null);
    }

    public void postAdEvent(@NonNull String event, @NonNull AdParams adParams, @Nullable String message) {
        postAdEvent(event, adParams, message, null);
    }

    public void postAdEvent(@NonNull String event, @NonNull AdParams adParams, @Nullable String message, @Nullable Map<String, Object> extras) {
        Map<String, Object> params = new HashMap<>();
        params.put(BwtAdParamConfig.KEY_AD_LOADER_ID, adParams.getAdLoaderId());
        params.put(BwtAdParamConfig.KEY_AD_ID, adParams.getAdId());
        params.put(BwtAdParamConfig.KEY_AD_EVENT, event);
        params.put(BwtAdParamConfig.KEY_AD_MSG, message == null ? "" : message);

        if (extras != null && extras.size() > 0) {
            params.putAll(extras);
        }

        invokeMethod(BwtAdMethodConfig.METHOD_ON_AD_EVENT, params);
    }

    //发送信息流自渲染的onload 把自渲染数据传出去
    public void postNativeAdEvent(@NonNull String event, @NonNull AdParams adParams,@NonNull Map<String, Object>loadNativeAd) {
        postNativeAdEvent(event, adParams, null,loadNativeAd);
    }

    public void postNativeAdEvent(@NonNull String event, @NonNull AdParams adParams, @Nullable String message,@NonNull Map<String, Object>loadNativeAd) {
        postNativeAdEvent(event, adParams, message, null,loadNativeAd);
    }

    public void postNativeAdEvent(@NonNull String event, @NonNull AdParams adParams, @Nullable String message, @Nullable Map<String, Object> extras,@NonNull Map<String, Object>loadNativeAd) {
        Map<String, Object> params = new HashMap<>();
        params.put(BwtAdParamConfig.KEY_AD_LOADER_ID, adParams.getAdLoaderId());
        params.put(BwtAdParamConfig.KEY_AD_ID, adParams.getAdId());
        params.put(BwtAdParamConfig.KEY_AD_EVENT, event);
        params.put(BwtAdParamConfig.KEY_AD_MSG, message == null ? "" : message);
        params.put(BwtAdParamConfig.KEY_NATIVEAD_DATA, loadNativeAd);
        params.put(BwtAdParamConfig.KEY_NATIVEAD_METHOD, BwtAdMethodConfig.METHOD_LOAD_NATIVE_AD);
        Log.d("adfadf","打ddd-"+params);
        if (extras != null && extras.size() > 0) {
            params.putAll(extras);
        }

        invokeMethod(BwtAdMethodConfig.METHOD_ON_AD_EVENT, params);
    }
    /**
     * 遍历找到指定广告，并释放
     *
     * @param adId 广告ID
     */
    private void loopNotifyOnAdRelease(String adId) {
        LogUtil.log("开始释放广告, adId: " + adId);
        for (OnAdReleaseListener listener : onAdReleaseListenerList) {
            listener.onAdRelease(adId);
        }
    }

    /**
     * 调用Flutter端方法
     *
     * @param methodName 方法名
     * @param params     参数
     */
    public void invokeMethod(String methodName, Map<String, Object> params) {
        try {
            channel.invokeMethod(methodName, params);
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取当前上下文，有Activity优先获取Activity
     */
    @Nullable
    public Context getCurrContext() {
        if (!activityList.isEmpty()) {
            return activityList.get(activityList.size() - 1);
        }
        return context;
    }

    @Nullable
    public BwtNativeExpressAdFactory getBwtNativeExpressAdFactory() {
        return bwtNativeExpressAdFactory;
    }

    public BwtBannerAdFactory getBwtBannerAdFactory() {
        return bwtBannerAdFactory;
    }


    public BwtUnifiedAdFactory getBwtUnifiedAdFactory() {
        return bwtUnifiedAdFactory;
    }

    public BwtServiceAdFactory getBwtServiceAdFactory() {
        return bwtServiceAdFactory;
    }
}
